﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System;
using System.Linq;

namespace OverStore.Sql.TableSchema
{
    /// <summary>
    /// Schema of database table.
    /// </summary>
    public sealed class Table
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="Table"/> class.
        /// </summary>
        public Table()
        {
            Columns = new Collection<ColumnBase>();
        }

        /// <summary>
        /// Get or set table name.
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Get or set collection of table columns.
        /// </summary>
        public IEnumerable<ColumnBase> Columns { get; set; }

        /// <summary>
        /// Gets or sets name of column contains values that allows to define actual type of object stored in specified table row.
        /// </summary>
        public string TypeDiscriminatorColumnName { get; set; }

        /// <summary>
        /// Gets or sets result that identify type of object stored in table.
        /// </summary>
        public string TypeId { get; set; }

        #region Table building methods

        /// <summary>
        /// Adds column to the table.
        /// </summary>
        public Table WithColumn(ColumnBase column)
        {
            if (Object.ReferenceEquals(column, null))
                throw new ArgumentNullException("column");
            Columns = (Columns ?? Enumerable.Empty<ColumnBase>()).Concat(new[] { column }).ToList();
            return this;
        }

        /// <summary>
        /// Adds the not-null key column with specified name.
        /// </summary>
        public Table Key<T>(string name)
        {
            if (String.IsNullOrEmpty(name))
                throw new ArgumentNullException("name");
            return WithColumn(new Key<T> { AllowNull = false, Name = name });
        }

        /// <summary>
        /// Adds the not-null key column which value is generated by database.
        /// </summary>
        public Table DbGeneratedKey<T>(string name)
        {
            if (String.IsNullOrEmpty(name))
                throw new ArgumentNullException("name");
            return WithColumn(new Key<T> { AllowNull = false, Name = name, IsDatabaseGenerated = true });
        }

        /// <summary>
        /// Adds nullable column with specified name.
        /// </summary>
        public Table NullableColumn<T>(string name)
        {
            if (String.IsNullOrEmpty(name))
                throw new ArgumentNullException("name");
            return WithColumn(new Column<T> { Name = name, AllowNull = true });
        }

        /// <summary>
        /// Adds not-null column with specified name.
        /// </summary>
        public Table Column<T>(string name)
        {
            if (String.IsNullOrEmpty(name))
                throw new ArgumentNullException("name");
            return WithColumn(new Column<T> { Name = name });
        }

        #endregion
    }
}